﻿using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UIElements;

namespace XLFrame.NodeEditor
{
    /// <summary>
    /// 结点样式处理
    /// </summary>
    public class NodeViewStyle
    {
        private readonly NodeViewBase m_nodeView;
        private VisualElement extensionContainer { get; set; }
        private VisualElement titleContainer { get; set; }
        private VisualElement inputContainer{ get; set; }
        private VisualElement outputContainer{ get; set; }
        private VisualElement titleButtonContainer{ get; set; }
        private VisualElement topContainer{ get; set; }
        
        private List<UnityAction> m_nodeStyleInits = new List<UnityAction>();
        
        private Dictionary<string,NodeStyleBase> m_nodeStyles = new Dictionary<string, NodeStyleBase>();
        
        /// <summary>
        /// 初始化重建是否以及完成
        /// </summary>
        private bool isInitEnd = false;
        
        public NodeViewStyle(NodeViewBase nodeView)
        {
            m_nodeView = nodeView;
            extensionContainer = m_nodeView.extensionContainer;
            titleContainer = m_nodeView.titleContainer;
            inputContainer = m_nodeView.inputContainer;
            outputContainer = m_nodeView.outputContainer;
            titleButtonContainer = m_nodeView.titleButtonContainer;
            topContainer = m_nodeView.topContainer;

            if (m_nodeView.IsNewNode)
            {
                m_nodeView.OnInitEndEvent += NodeViewOnOnNodeDataLoadingDataEnd;
            }
            else
            {
                m_nodeView.OnNodeDataLoadingDataEndEvent += NodeViewOnOnNodeDataLoadingDataEnd;
            }
        }

        /// <summary>
        /// 当数据加载完成后调用
        /// </summary>
        private void NodeViewOnOnNodeDataLoadingDataEnd()
        {
            m_nodeStyleInits.ForEach(action => action.Invoke());
            isInitEnd = true;
        }
        
        public NodeStyleBase GetNodeStyle(string styleTypeID)
        {
            return m_nodeStyles.TryGetValue(styleTypeID, out NodeStyleBase style) ? style : null;
        }

        /// <summary>
        /// 获取指定容器
        /// </summary>
        /// <param name="container"></param>
        /// <returns></returns>
        private VisualElement GetContainer(NodeStyleData.NodeStyleContainer container)
        {
            switch (container)
            {
                case NodeStyleData.NodeStyleContainer.extensionContainer:
                    return extensionContainer;
                case NodeStyleData.NodeStyleContainer.mainContainer:
                    return m_nodeView.mainContainer;
                case NodeStyleData.NodeStyleContainer.titleContainer:
                    return titleContainer;
                case NodeStyleData.NodeStyleContainer.inputContainer:
                    return inputContainer;
                case NodeStyleData.NodeStyleContainer.outputContainer:
                    return outputContainer;
                case NodeStyleData.NodeStyleContainer.titleButtonContainer:
                    return titleButtonContainer;
                case NodeStyleData.NodeStyleContainer.topContainer:
                    return topContainer;
            }

            return null;
        }
        
        /// <summary>
        /// 添加一个样式容器到extensionContainer
        /// </summary>
        public void AddNodeStyle<T>(NodeStyleData.NodeStyleContainer container = NodeStyleData.NodeStyleContainer.extensionContainer) 
            where T:NodeStyleBase,new()
        {
            var style = NodeStyleBase.CreateNodeStyle<T>(container);
            m_nodeView.NodeData.NodeStyleDatas.Add(style.StyleData);
            AddNodeStyle(style);
        }
        
        /// <summary>
        /// 添加样式到extensionContainer
        /// </summary>
        /// <param name="style"></param>
        public void AddNodeStyle(NodeStyleBase style)
        {
            if (m_nodeView.IsNewNode)
            {
                INodeStyleInit styleInit = style;
                styleInit.AddStyleInit(m_nodeView);
            }
          
            AddContainer(style.StyleData.StyleContainer,style);
            
            m_nodeStyles.TryAdd(style.StyleData.StyleTypeID,style);
        }
        
        /// <summary>
        /// 调用所有样式的初始化
        /// </summary>
        public void CallNodeStyleInit()
        {
            foreach (var item in m_nodeStyles)
            {
                INodeStyleInit styleInit = item.Value;
                styleInit.AddStyleInit(m_nodeView);
            }
        }

        /// <summary>
        /// 添加进容器并刷新(等到node.Init执行完毕后)
        /// </summary>
        /// <param name="container"></param>
        /// <param name="ve"></param>
        private void AddContainer(NodeStyleData.NodeStyleContainer container,VisualElement ve)
        {
            if (isInitEnd)
            {
                GetContainer(container).Add(ve);
                m_nodeView.RefreshExpandedState();
            }
            else
            {
                m_nodeStyleInits.Add(() =>
                {
                    GetContainer(container).Add(ve);
                });
            }
        }
        
        
    }
}